package com.one.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.one.Mapper.UserMapper;
import com.one.annotation.RequestUser;
import com.one.bean.User;
import com.one.config.WechatPayConfig;
import com.one.constant.RedisPrefixConstant;
import com.one.constant.WechatPayConstant;
import com.one.service.WechatPayService;
import com.one.util.HttpClient4Util;
import com.one.util.LocalDateUtils;
import com.one.util.RedisUtils;
import com.one.util.WechatPayUtil;
import com.one.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import static com.one.util.LocalDateUtils.DATETIME_PATTERN;

/**
 * @author: tzy
 * @create: 2022/1/4
 * @FileName: WechatPayServiceImpl
 * @Description: 微信支付业务接口实现类
 */
@Service
@Slf4j
public class WechatPayServiceImpl implements WechatPayService {

    @Autowired
    private WechatPayConfig wechatPayConfig;
    @Autowired(required = false)
    private UserMapper userMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired(required = false)
    private LocalDateUtils localDateUtils;
    @Override
    public String wechatPayUnifiedOrderParamsXml(String body,Integer totalFee,String token) throws Exception{
        //微信统一下单接口，要求将集合M内非空参数值的参数按照参数名ASCII码从小到大排序（字典序），参数名区分大小写
        Map<String,String> paramsMap = new TreeMap<>();
        //公众账号ID
        paramsMap.put("appid",wechatPayConfig.getAppId());
        //商户号
        paramsMap.put("mch_id",wechatPayConfig.getMchId());
        //设备号，PC网页或公众号内支付可以传"WEB"
        paramsMap.put("device_info","WEB");
        //随机字符串，长度要求在32位以内，增加签名的安全性
        paramsMap.put("nonce_str", WechatPayUtil.generateNonceStrUseRandom());
        //商品的简要描述
        paramsMap.put("body",body);
        //商户订单号
        paramsMap.put("out_trade_no",WechatPayUtil.generateOutTradeNo());
        //标价金额
        paramsMap.put("total_fee",totalFee.toString());
        //附加数据
        paramsMap.put("attach", token);
        //终端ip
        paramsMap.put("spbill_create_ip","127.0.0.1");
        //通知的回调地址，异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数
        paramsMap.put("notify_url",wechatPayConfig.getNotifyUrl());
        //交易类型
        paramsMap.put("trade_type", WechatPayConstant.WECHAT_PAY_TRADE_TYPE_NATIVE);
        //商品编号，trade_type=NATIVE,此参数必传
        paramsMap.put("product_id", WechatPayUtil.generateNonceStrUseUUID(10));

        // 签名，是使用上面所有参数进行签名，都是在参数确定最后，进行签名操作，自己不参与
        // 需要传给微信官方，进行签名校验（微信官方会根据上面所有参数，重新签名，对比传递的sign值），防止接口交互不安全
        paramsMap.put("sign", WechatPayUtil.generateSignature(paramsMap, wechatPayConfig.getMchKey()));

        // 将所有参数转换为xml字符串，返回
        return WechatPayUtil.generateMapToXml(paramsMap);
    }

    @Override
    public Map<String, String> wechatPayUnifiedOrder(String unifiedOrderParamsXml) throws Exception {
        // 发送post请求，到微信统一下单接口
        String unifiedOrderReturnXml = HttpClient4Util.getResponse4PostByString(wechatPayConfig.getOrderUrl(), unifiedOrderParamsXml, WechatPayConstant.WECHAT_PAY_ENCODING_UTF8);

        // 将微信统一下单返回，转换为map集合
        return WechatPayUtil.generateXmlToMap(unifiedOrderReturnXml);
    }

    @Override
    public String wechatPayUnifiedNotifyResole(String unifiedNotifyResultXml) throws Exception {
        // 将微信支付异步回调的xml字符串，转换为map
        Map<String, String> unifiedNotifyResultMap = WechatPayUtil.generateXmlToMap(unifiedNotifyResultXml);

        // 只处理成功回调
        if(WechatPayConstant.WECHAT_PAY_RETURN_CODE_SUCCESS.equals(unifiedNotifyResultMap.get("return_code"))
                && WechatPayConstant.WECHAT_PAY_RESULT_CODE_SUCCESS.equals(unifiedNotifyResultMap.get("result_code"))){
            // 签名校验
            if(WechatPayUtil.isSignatureValid(unifiedNotifyResultMap, wechatPayConfig.getMchKey())){
                // 签名校验成功
                // TODO 进行业务处理，比如改订单状态，增加积分等
                //在redis中查询是否存在用户会员的key
                String token = unifiedNotifyResultMap.get("attach");
                UserVo userVo = JSON.toJavaObject(JSON.parseObject(redisUtils.get(token).toString()),UserVo.class);
                int num = Integer.parseInt(unifiedNotifyResultMap.get("total_fee"));
                if (redisUtils.hasKey(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId())){
                    log.info("------ 往redis中添加用户会员信息,信息存在,增加时长 ------");
                    //会员未过期，添加会员时长
                    Long time = null;
                    time = redisUtils.getExpire(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId());
                    LocalDateTime localDateTime1=LocalDateTime.parse(redisUtils.get(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId()).toString());
                    redisUtils.set(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId(),localDateTime1.plusDays(7*num));
                    redisUtils.expire(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId(),time + (604800*num));
                }else {
                    //用户不是会员，添加会员信息
                    log.info("------ 往redis中添加用户会员信息,信息不存在,创建用户vip信息 ------");
                    LocalDateTime localDateTime = LocalDateUtils.plus(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(), 7, ChronoUnit.DAYS);

                    redisUtils.set(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId(),localDateTime,(604800*num));
                    log.info("------ 更新user表中用户的会员信息 ------");
                    User user = new User();
                    user.setId(userVo.getUserId());
                    user.setMember(true);
                    userMapper.updateById(user);
                    log.info("------ 更新redis中用户的token信息 ------");
                    userVo.setMember(true);
                    redisUtils.set(RedisPrefixConstant.LOGIN_TOKEN+token,userVo);
                }
                return WechatPayConstant.WECHAT_PAY_NOTIFY_RESPONSE_SUCCESS;
            }
        }

        return WechatPayConstant.WECHAT_PAY_NOTIFY_RESPONSE_FAIL;
    }

    /**
     * @author: tzy
     * @date: 2022/1/17
     * @return: java.lang.Boolean
     * @Description: 更新user表的会员信息
     */
    @Override
    public Boolean modUser(User user) {

        //调用sql语句
        return userMapper.updateById(user) > 0;
    }



    /**
     * @author: tzy.
     * @date: 2022/1/21
     * @return:
     * @Description: 查询用户的会员到期时间
     */
    @Override
    public String findUserMemberDate(UserVo userVo) {
//        log.info("[{}]",redisUtils.get("VIP:1"));
//        LocalDateTime localDateTime1=localDateUtils.parseLocalDateTime(redisUtils.get("VIP:1").toString(),DATETIME_PATTERN);
//        redisUtils.set("VIP:1",localDateTime1.plusDays(7));
        if (redisUtils.get(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId()) == null){
            return null;
        }else {
            return redisUtils.get(WechatPayConstant.REDIS_MEMBER_UNIFIED_PREFIX + userVo.getUserId()).toString();
        }

    }
}